/*
 * GTF writing plugin for BAT.
 * Copyright (C) 2006 Bob Zimmermann <rpz@cse.wustl.edu>
 *
 *  This file is a part of BAT.
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * BAT_GTF_Writer.c
 *
 * BAT_GeneTab writer class that outputs BAT-formatted files.
 *
 * $Id: BAT_GTF_Writer.c 1408 2006-09-20 20:28:50Z rpz $
 *
 */

#include "BAT_GTF_Writer.h"

/* FIXME: uses private functions, probably shouldn't */

BAT_Write_Plugin BAT_GTF_Write_Plugin = {
  BAT_GTF_Writer_Type,
  "gtf",
  BAT_GTF_Write_Context_new,
  BAT_GTF_Write_Context_delete,
  BAT_GTF_Writer_output_gene_table,
  BAT_GTF_Writer_output_gene,
  BAT_GTF_Writer_output_transcript,
  BAT_GTF_Writer_output_feature,
  BAT_GTF_Writer_output_free_feature,
  BAT_GTF_Writer_output_attribute
};

void *
BAT_GTF_Write_Context_new()
{
  BAT_GTF_Write_Context *w;
  w = malloc(sizeof(BAT_GTF_Write_Context));
  return w;
}

void
BAT_GTF_Write_Context_delete(void *w, int befrei)
{
  if (befrei)
    free(w);
}

void
BAT_GTF_Writer_output_gene_table(void *wc, FILE * fh, BAT_GeneTab * bat)
{
  da_pos_t i, sz;
  BAT_Gene **genes;

  genes = (BAT_Gene **) BAT_GeneTab_get_genes(bat, &sz);
  for (i = 0; i < sz; i++)
    BAT_GTF_Writer_output_gene(wc, fh, genes[i]);
}



void
BAT_GTF_Writer_output_gene(void *wc, FILE * fh, BAT_Gene * gene)
{
  da_pos_t i, sz;
  BAT_Transcript **txs;

  txs = (BAT_Transcript **) BAT_Gene_get_transcripts(gene, &sz);
  for (i = 0; i < sz; i++)
    BAT_GTF_Writer_output_transcript(wc, fh, txs[i]);
}


void
BAT_GTF_Writer_output_transcript(void *wc, FILE * fh, BAT_Transcript * tx)
{
  da_pos_t i, fsz;
  BAT_Feature **feats;

  feats = BAT_Transcript_get_features(tx, &fsz);
  for (i = 0; i < fsz; i++)
    BAT_GTF_Writer_output_feature(wc, fh, feats[i]);
}


void
BAT_GTF_Writer_output_free_feature(void *wc, FILE * fh, BAT_Free_Feature * feat)
{
  da_pos_t i, asz;
  BAT_Attribute **attrs;

  if (feat->comment != NULL)
    BAT_GTF_Writer_output_comment_lines(wc, fh, feat->comment);
  fprintf(fh, "%s\t%s\t%s\t%ld\t%ld\t%d\t%c\t%c\t", feat->seqname, feat->source,
	  BAT_Feature_Type_get_str(feat->type), feat->start, feat->end,
	  feat->score, BAT_Strand_get_strand_char(feat->strand),
	  BAT_Free_Feature_get_frame_char(feat));

  attrs = BAT_Free_Feature_get_attributes(feat, &asz);
  if (asz > 0) {
    /* we have to do this because trailing spaces is illegal */
    BAT_GTF_Writer_output_attribute(wc, fh, attrs[0]);
    for (i = 1; i < asz; i++) {
      fprintf(fh, " ");
      BAT_GTF_Writer_output_attribute(wc, fh, attrs[i]);
    }
  }
  if (feat->comment != NULL)
    BAT_GTF_Writer_output_inline_comment(wc, fh, feat->comment);
  fprintf(fh, "\n");
}

void
BAT_GTF_Writer_output_feature(void *wc, FILE * fh, BAT_Feature * feat)
{
  da_pos_t i, asz;
  BAT_Attribute **attrs;

  if (feat->comment != NULL)
    BAT_GTF_Writer_output_comment_lines(wc, fh, feat->comment);
  fprintf(fh, "%s\t%s\t%s\t%ld\t%ld\t%d\t%c\t%c\t",
	  BAT_Feature_get_seqname(feat), BAT_Feature_get_source(feat),
	  BAT_Feature_Type_get_str(feat->type), feat->start, feat->end,
	  feat->score, BAT_Strand_get_strand_char(BAT_Feature_get_strand(feat)),
	  BAT_Feature_get_frame_char(feat));

  /* attr_alloc = feat->attributes; */
  /* XXX: doesn't this go against what my original plan was?  to keep some
   * attribute there so all attributes are equal? */
  fprintf(fh, "gene_id \"%s\"; transcript_id \"%s\";",
	  BAT_Feature_get_gene_id(feat), BAT_Feature_get_transcript_id(feat));

  attrs = BAT_Feature_get_attributes(feat, &asz);
  for (i = 0; i < asz; i++) {
    fprintf(fh, " ");
    BAT_GTF_Writer_output_attribute(wc, fh, attrs[i]);
  }
  if (feat->comment != NULL)
    BAT_GTF_Writer_output_inline_comment(wc, fh, feat->comment);
  fprintf(fh, "\n");
}

void
BAT_GTF_Writer_output_inline_comment(void *wc, FILE * fh, BAT_Comment * cmt)
{
  if (cmt->inltext != NULL && strlen(cmt->inltext) > 0)
    fprintf(fh, "%*c# %s", cmt->offset, ' ', cmt->inltext);
}


void
BAT_GTF_Writer_output_comment_lines(void *wc, FILE * fh, BAT_Comment * cmt)
{
  da_pos_t i, sz;
  /*darray_t *alloc; */
  char **lines;

  /* FIXME: should have a get_lines func */
  lines = (char **) darray_get_array(cmt->lines);
  sz = darray_size(cmt->lines);
  for (i = 0; i < sz; i++)
    fprintf(fh, "%s", lines[i]);
  /*
   * alloc = cmt->_children;
   * sz = darray_size(alloc);
   * for (i = 0; i < sz; i++)
   * fprintf(*((char *) darray_get(alloc, i)), fh);
   */
  /*
   * &sz = darray_size(alloc); lines = (char
   * ***)darray_get_array(alloc); for(i = 0; i < sz; i++) fprintf(fh,
   * "%s", *lines[i]);
   */
}


void
BAT_GTF_Writer_output_attribute(void *wc, FILE * fh, BAT_Attribute * attr)
{
  fprintf(fh, "%s \"%s\";", attr->key, attr->value);
}
